package org.spiderflow.redis.executor.function;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.spiderflow.annotation.Comment;
import org.spiderflow.annotation.Example;
import org.spiderflow.executor.FunctionExecutor;
import org.spiderflow.expression.DynamicMethod;
import org.spiderflow.redis.model.RedisSource;
import org.spiderflow.redis.service.RedisSourceService;
import org.spiderflow.redis.service.RedissonSourceService;
import org.spiderflow.redis.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
import redis.clients.util.SafeEncoder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Comment("redisson常用方法")
public class RedissonFunctionExecutor extends HashMap<String, Object> implements FunctionExecutor{
	
	private static final long serialVersionUID = 924273531304909956L;

	public static volatile Map<String,RedissonClient> REDIS_CACHED_TEMPLATE = new HashMap<String, RedissonClient>();

	private static RedissonSourceService redissonSourceService;
	
	@Override
	public String getFunctionPrefix() {
		return "redisson";
	}
	
	private static RedissonClient findRedisTemplate(String alias){
		RedissonClient redissonClient = REDIS_CACHED_TEMPLATE.get(alias);
		if(redissonClient == null){
			RedisSource redisSource = redissonSourceService.getOne(new QueryWrapper<RedisSource>().eq("alias", alias).orderByDesc("create_date"));
			if(redisSource == null){
				throw new NullPointerException("找不到Redis数据源'" + alias +"'");
			}
			redissonClient = RedisUtils.createRedisson(redisSource);
			REDIS_CACHED_TEMPLATE.put(alias, redissonClient);
		}
		return redissonClient;
	}
	

	
	@Override
	public Object get(Object key) {
		return use(key == null ? null : key.toString());
	}
	
	@Comment("选择数据源")
	@Example("${redisson.use('aliasName')}或${redisson.aliasName}")
	public static synchronized DynamicMethod use(String alias){
		return createDynamicMethod(alias,findRedisTemplate(alias));
	}
	
	private static DynamicMethod createDynamicMethod(String alias,RedissonClient redisson){
		return new DynamicMethod() {

			@Override
			public Object execute(String methodName, List<Object> parameters){

				if(parameters==null || parameters.size()==0 || parameters.size()>2){
					return null;
				}

				String key=parameters.get(0).toString();
				Integer waitTime=10;
				if(parameters.size()==2){
					try {
						Integer time = Integer.parseInt(parameters.get(0).toString());
						if (time != null) {
							waitTime = time;
						}
					}catch (Exception e){

					}
				}

				;

				switch (methodName){
					case "lock":
						try {
							RLock lock=null;
							lock = redisson.getLock(key);
							lock.tryLock(100, waitTime, TimeUnit.SECONDS);
						}catch (InterruptedException e){
						}finally { }
						return 1;
					case "unlock":
						//获得锁的线程不是释放锁的线程，
						return 1;
					default:
						return null;
				}
			}


		};
	} 

	@Autowired
	public void setRedisSourceService(RedissonSourceService redissonSourceService) {
		RedissonFunctionExecutor.redissonSourceService = redissonSourceService;
	}

}
